﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EasyCore.Locks
{
    /// <summary>
    /// 等值锁定
    /// 锁定给定内容
    /// 内容必须实现IComparable接口，若Comparable比较两个对象是同一个值，
    /// 则在相等对象上执行的操作是同步的
    /// 实际上未对给定对象进行锁定，在外部可以调用lock等
    /// </summary>
    public class EquivalentLock<T> where T : IComparable<T>
    {
        Dictionary<T, Semaphore> t2Event = new Dictionary<T, Semaphore>();

        System.Threading.SpinLock sl = new SpinLock();
        /// <summary>
        /// 进入锁定内容
        /// </summary>
        /// <param name="lockObj">被锁定的内容</param>
        public void Enter(T lockObj)
        {
            bool lockTaken = false;
            sl.Enter(ref lockTaken);
            if (!t2Event.ContainsKey(lockObj))
            {
                t2Event.Add(lockObj, new Semaphore(1, 1));
            }
            sl.Exit();
            t2Event[lockObj].WaitOne();
        }
        /// <summary>
        /// 退出锁定内容
        /// </summary>
        /// <param name="lockObj">锁定的内容</param>
        public void Exit(T lockObj)
        {
            if (!t2Event.ContainsKey(lockObj))
            {
                throw new KeyNotFoundException();
            }
            t2Event[lockObj].Release();
        }
        /// <summary>
        /// 释放存储资源
        /// </summary>
        public void Free()
        {
            t2Event.Clear();
        }
    }
}
